PROGRAMACIÓN
ORIENTADA A
EVENTOS

“El lograr una comprensión profunda del proceso de eventos es todavía un desafío” (Ted Faison)

“Un lenguaje de programación es de bajo nivel cuando sus programas requieren atención a lo irrelevante” (Alan J. Perlis)



El Concepto de Evento

Un evento es algo que ocurre en un sistema y que interesa conocer o detectar con el fin de realizar un determinado proceso asociado a dicho evento.

La forma general de especificar un evento es “Si condición, entonces acción”.

Los eventos pueden ser internos y externos:
Especificación en MENTAL

Un evento se especifica mediante una expresión genérica condicional:
Observaciones
Proceso de un evento

Cuando se produce un evento, se realiza el siguiente proceso:
  1. Se pone en pausa el proceso en curso.
  2. Se procesa el evento, es decir, se ejecuta la acción asociada al evento.
  3. Se continúa con la evaluación de la expresión en curso, a menos que en el paso anterior, se produzca una parada, por ejemplo, por la detección de un error.

Eventos con nombre y anónimos

Un evento con nombre es un evento al que se le asigna un nombre para poder hacer referencia a él a lo largo de un programa. La forma es en donde e es el nombre del evento.

Un evento anónimo es el que se define sin nombre, especificando directamente la expresión genérica correspondiente:

Eventos específicos y genéricos

La expresión genérica que especifica un evento puede estar parametrizada o no: Ejemplos de eventos específicos:
  1. Detectar si a es un elemento del grupo (secuencia o conjunto) g:

    ⟨( a∈g → acción )⟩

  2. Detectar si la variable u tiene un valor mayor que 1 y menor que 10:

    ⟨( (u>1 → u<10) → acción )⟩

  3. Detectar si un grupo g contiene a, b o c:

    ⟨( {(a∈g)? (b∈g)? (c∈g)? }↓ → acción )⟩

    De forma más compacta:

    ⟨( {[([a b c]∈g)?]}↓ → acción )⟩

  4. Detectar si algún elemento de una secuencia s pertenece a g:

    ⟨( {[s↓∈g)?]}↓ → acción )⟩
Ejemplos de eventos genéricos:
  1. Detectar si un elemento a pertenece a un grupo (secuencia o conjunto).

    ⟨( (x = {x↓}) → a∈x → acción )⟩

  2. Detectar un grupo (secuencia o conjunto) de longitud mayor que 10:

    ⟨( (x# > 10) → acción )⟩

  3. Detectar si se evalúa una condición simple:

    ⟨( (xy) → acción )⟩

  4. Detectar si se evalúa una condición completa:

    ⟨( (xy →' z) → acción )⟩

Eventos parametrizados

Son eventos definidos mediante parámetros. Pueden ser, a su vez, específicos o genéricos, dependiendo de que incluyan, a su vez, parámetros en su definición.

Ejemplo de evento parametrizado específico:

⟨( e(u v) = ⟨( (a>u → a<v) → acción )⟩ )⟩ // definición evento

(e(3 9)) // activación del evento ⟨( (a>3 → a<9) → acción )⟩


Ejemplo de evento parametrizado genérico:

⟨( e(u v) = ⟨( (x>ux<v) → acción )⟩ )⟩ // definición evento

e(3 9) // activación evento ⟨( (x>3 → x<9) → acción )⟩


En este caso existen dos tipos de parámetros: los de su definición o internos (x) y los externos (u y v).


Eventos relativos

Los eventos anteriores eran de tipo absoluto (o globales), pues afectaban a todas las expresiones que se evalúan. Pero puede haber eventos que sólo se apliquen a una determinada expresión. Son los eventos relativos (o locales). Se especifican mediante siendo x la expresión potencial fuente (productora del evento) y ⟨e⟩ la expresión genérica que define el evento relativo.

Como en el caso de los eventos absolutos, los eventos relativos pueden ser específicos o genéricos, dependiendo de que se definan o no parámetros.

Ejemplos:
  1. Impedir que una variable (resultado de una operación) supere un determinado valor.

    (y = x*x + 7)/⟨( y>1000 → (y = 1000) )⟩

  2. Impedir que el resultado de una función determinada supere un cierto valor, independientemente del argumento.

    ⟨( f(x) = x*x )⟩/⟨( f(x)>1000 → (f(x) = 1000) )⟩

Eventos dinámicos

Un evento dinámico es un evento que cambia durante la ejecución de un programa. Puede cambiar de muchas formas: haciendo variable la condición, la acción o ambas, parametrizando el evento, etc. Ejemplos:
  1. Condición variable.

    ( cond = (x>10)° ) // condición inicial
    ⟨( cond → x=10 )⟩ // definición del evento
    (x = 20)
    x // ev. 10
    ...
    ( cond = (2*x > 20)° ) // nueva condición
    (x = 5)
    x // ev. 5


  2. Acción variable.

    ( accion = (x=10)° ) // acción inicial
    ⟨( x>10 → accion )⟩ // definición del evento
    (x = 20)
    x // ev. 10
    ...
    ( accion = (x = 2*x)° ) // nueva acción
    (x = 20)
    x // ev. 40


  3. Evento completo variable.

    ( evento = (x>10 → x=10)° ) // evento inicial
    ⟨( evento )⟩ // definición del evento
    (x = 20)
    x // ev. 10
    ...
    ( evento = (x>20 → x=30)° ) // nuevo evento
    (x = 25)
    x // ev. 30

Evento nulo

Un evento nulo es aquel en el que la condición o la acción de la expresión genérica es nula. Se dice que el evento es nulo porque no produce ningún efecto: Utilizando una variable (como condición o como acción), que puede tomar un valor nulo o un valor concreto no nulo, podemos activar o desactivar el evento, en su aspecto de condición o de acción. Ejemplos:
  1. (cond = θ) // condición nula
    ⟨( cond → acción )⟩ // evento desactivado por condición nula


  2. (accion = θ) // acción nula
    ⟨( cond → accion )⟩ // evento desactivado por acción nula

Detección de cambios

En un entorno dinámico, las expresiones pueden cambiar con el tiempo. Si se desea capturar el evento de que una cierta expresión cambia, puede hacerse, pero es necesario incluir variables adicionales que registren los cambios.

Ejemplo: Queremos detectar cambios en la variable x.
Eventos de orden superior (eventos de eventos)

Un evento de evento (evento de orden 2) es un evento que sucede durante el proceso asociado a un evento normal (de orden 1).

Los eventos de orden 2 pueden ser absolutos o relativos al proceso del evento. La forma relativa sería: Ejemplo: Detectar, solo durante el proceso de un evento, si una variable supera un cierto valor. Análogamente, también pueden especificarse eventos de niveles superiores (3, 4, etc.).


Ejemplos de eventos restrictivos
  1. Queremos que una variable determinada v durante un proceso, no supere nunca el valor 10. Si es mayor, debe hacerse automáticamente igual a 10.


  2. En una secuencia determinada s de dos componentes, inicialmente con el valor (3 7), queremos que la suma sea siempre 10, de tal forma que el segundo componente se ajuste siempre al valor del primero.


  3. Impedir que una secuencia s tenga más de dos componentes.


Seguridad y excepciones mediante restricciones

El mecanismo de restricciones es aplicable a temas de seguridad y para el control de excepciones. Los siguientes son ejemplos de restricciones genéricas (utilizan parámetros).
  1. División por cero.
    Queremos interceptar las divisiones por cero, antes de que se produzcan, y obtener en la variable error la expresión nula θ si no hay error o un texto con el mensaje “Intento de división por cero en exp”, siendo exp la expresión a la que se intenta aplicar la división por cero. A continuación, parar el proceso.

    ⟨( (error = θ) ←' (x÷0) → ((error = "Intento de división por cero en " x) ■) )⟩

  2. Con el objeto de evitar problemas de memoria, queremos impedir que toda secuencia x sea de longitud mayor que 1000, impidiendo las asignaciones del tipo (x\i = y) con i mayor que 1000.

    ⟨( ((x\i) = θ) ← i>1000 )⟩

Ventajas de MENTAL en la Programación Orientada a Eventos


Adenda

Historia de los eventos en el software

Los eventos nacieron en el mundo del software a principios de los 1980s con el lenguaje Smalltalk para mantener sincronizadas las partes de un sistema. Pero dos fueron sus grandes motores: 1) a nivel externo, a nivel usuario, las interfaces gráficas de usuario de los sistemas operativos, como Microsoft Windows; 2) a nivel interno, la aparición de Visual Basic a principios de los 1990s.

Con la irrupción de Internet, surgieron los sistemas “push” en los que los usuarios se suscriben a temas que le interesan y reciben automáticamente notificaciones de novedades.


Implementación clásica de un sistema orientado a eventos

Cuando se utiliza la programación orientada a eventos como único paradigma de programación con los lenguajes tradicionales, la ejecución del programa está determinada únicamente por el proceso asociado a los eventos. Se implementa de la forma siguiente:
  1. Se realizan las inicializaciones de código y datos.

  2. Se especifican los eventos que se contemplan en el sistema.

  3. Se desarrolla un “bucle de eventos” (event loop), un bucle que espera a que se produzca un evento. Cuando se produce, invoca al manejador (handler) asociado a dicho evento, que lo procesa, y vuelve a quedar en espera a que se produzca otro evento.
Por ejemplo, programas interactivos de proceso de textos, de hoja de cálculo, de dibujo, de presentaciones, etc. se arrancan y quedan a la espera de las acciones del usuario sobre la interfaz gráfica de usuario que presenta el programa.

En MENTAL todo es más simple y directo. No se necesita un bucle de eventos porque la semántica de la expresión genérica ya lo realiza implícitamente. Y el manejador del evento reside en el código del lenguaje asociado a la condición.

Mientras la noción de evento es natural, su soporte en los lenguajes de programación suele ser poco expresivo, no genérico y difícil de utilizar. Diversos lenguajes soportan (cada uno a su manera) la orientación a eventos, como Visual Basic, Tcl/Tk, Java, Delphi, PowerBuilder, C#, FoxPro, Simula, etc. En Inteligencia Artificial no se habla de eventos, sino de “demonios” (demons), entidades que están alertas a la aparición de eventos específicos y que disparan acciones o procesos asociados cuando se producen.


Bibliografía